<?php

namespace App\Http\Middleware\OpenShop;

use App\Library\Rms\RmsUserApi;
use App\Enums\BaseErrorCode;
use App\Enums\Kms\UserErrorEnum;
use App\Enums\OpenShop\InvestmentPromotion\ErrCode;
use App\Exceptions\Custom\CustomHttpResponseException;
use App\Exceptions\Custom\ResponseHttpException;
use App\Models\Kms\App\ClientsModel;
use App\Models\Kms\Auth\KmsClientModel;
use App\Models\Kms\User\KmsUser;
use App\Models\Common\ConfigModel;
use App\Service\OpenShop\Feishu\LoginService;
use App\Service\OpenShop\SiteLocation\AuthService;
use App\Service\OpenShop\User\RmsUserService;
use App\Support\AppletEncrypt;
use Closure;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\AuthManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\UnauthorizedException;
use Illuminate\Validation\ValidationException;
use Kuafu\GeneralFs\BuildFs;
use Laravel\Passport\Passport;
use Lcobucci\JWT\Parser;
use Kuafu\IpWhite\Service\IpWhiteService;

class AppletAuth
{
    public static ?object $userInfo = null;


    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (config('app.env') == 'dev' && !$request->header('APPLET_TOKEN')) {
            self::$userInfo = (object)(new RmsUserApi())->getUserInfoByMobiles(['13917836275'])['data'][0] ?? [];

            $userInfo          = RmsUserService::getRmsAuthUserInfo(self::$userInfo->id);
            $request->userInfo = (object)$userInfo['data'];

            $action         = $request->route()->getAction('controller');
            $actionSplit    = explode('Controllers\\', $action);
            $controllerList = strtolower(str_replace(['@', '\\', 'Controller'], ['.', '.', ''], $actionSplit[1]));

            $request->controllerUri = $controllerList;

            $request->setUserResolver(function () use ($userInfo) {
                return (object)$userInfo["data"];
            });

            return $next($request);
        }

        if ($bearerToken = $request->bearerToken()) {

            // 选品建议飞书端
            $headerPlatformName = $request->header('platformName','');
            if ($headerPlatformName == UserPermissionAuth::MODULE_PRODUCT_SELECTION_PROPOSAL) {// 选品建议
                return $this->productSelectionProposalAuthorization($request, $next);
            }
            return $this->kmsAuthorization($request, $next, $bearerToken);
        } else {

            //从header获取token值
            $token = $request->header('APPLET-TOKEN');
            if (!$token) {
                Log::info(sprintf('飞书小程序登录失败，header头缺少applet-token。url:%s,headers:%s', $request->path(),
                    json_encode($request->header(), JSON_UNESCAPED_UNICODE)));
                throw new ResponseHttpException(20000, null, '网络不稳定，请点击右上角重新进入应用');
            }

            self::convertAppIdToPlatformName($request);

            //检查token是否是小程序平台生成

            try {

                //检查token是否是小程序平台生成
                try {
                    $decryptData = AppletEncrypt::getInstance()->decryptData($token);
                } catch (\Exception $exception) {
                    throw new ResponseHttpException(BaseErrorCode::$TOKEN_ERROR_EXIST);
                }

                // 校验ip白名单
                $testerUserIds = json_decode(ConfigModel::getSingleConfig('ipWhite', 'ipWhiteTestUserIds', null,
                        getSwitchCacheTime(600)) ?? '[]', true);
                $check         = (new IpWhiteService($decryptData['userId'], $decryptData['openId'], $request))
                    ->setTesterUserIds($testerUserIds)
                    ->checkIp($decryptData['ip'] ?? '', false);
                if (!$check) {
                    throw new ResponseHttpException(IpWhiteService::ERR_RESPONSE_CODE, null,
                        '已在其他设备登录，请退出后重新登录');
                }

                $headerPlatformName = $request->header('platformName');
                if ($headerPlatformName == 'open') {
                    $headerPlatformName = 'openShop';
                }

//                if ($decryptData['platformName'] != $headerPlatformName) {
//                    throw new ResponseHttpException(BaseErrorCode::$TOKEN_PLATFORM_ERROR);
//                }
                //检查token是否失效,如果失效重新登陆
                AppletEncrypt::getInstance()->checkInvalidToken($token);
                //检查token
                AppletEncrypt::getInstance()->checkExpireToken($token);

                //写入用户信息
                self::$userInfo = (object)AuthService::getRmsUserInfo($request);

                $userInfo = RmsUserService::getRmsAuthUserInfo(self::$userInfo->userId, 0);

                if (empty($userInfo)) {
                    Log::info("登录信息记录:", [
                        'token'       => $token,
                        'userInfo'    => self::$userInfo,
                        'rmsUserInfo' => $userInfo
                    ]);
                    throw new ResponseHttpException(BaseErrorCode::$USER_IS_NOT_EXIST);
                }

                $request->userInfo = (object)$userInfo['data'];
                $action            = $request->route()->getAction('controller');
                $actionSplit       = explode('Controllers\\', $action);
                $controllerList    = strtolower(str_replace(['@', '\\', 'Controller'], ['.', '.', ''],
                    $actionSplit[1]));
                // 设置当前请求的uri
                $request->controllerUri = $controllerList;

                $request->setUserResolver(function () use ($userInfo) {
                    return (object)$userInfo["data"];
                });

                return $next($request);
            } catch (\Exception $exception) {
                handleException($exception);
            }
        }
    }

    public function kmsAuthorization(Request $request, Closure $next, string $bearerToken)
    {
        $auth = Auth::guard("kmsApi");
        if ($auth->check()) {
            $userMap = KmsUser::query()->where("rmsUserId", $auth->user()->rmsUserId)->get();
            if ($userMap->where("isExited", 0)->count() == 0) {
                throw new ResponseHttpException(UserErrorEnum::$USER_EXITED);
            }
            $clientId = (new Parser())->parse($bearerToken)->getClaim("aud");
            if (
                Passport::clientModel()::where("id", $clientId)->where("revoked", 0)->first()
                &&
                ClientsModel::query()->where("clientId", $clientId)
                            ->where("status", ClientsModel::STATUS_NORMAL)
                            ->first()
            ) {
                $userInfo                   = RmsUserService::getRmsAuthUserInfo($auth->user()->rmsUserId, 0);
                $userInfo["data"]["userId"] = $userInfo["data"]["id"];
                self::$userInfo             = (object)$userInfo["data"];
                if (empty($userInfo)) {
                    Log::info("登录信息记录:", [
                        'token'       => $bearerToken,
                        'userInfo'    => self::$userInfo,
                        'rmsUserInfo' => $userInfo
                    ]);
                    throw new ResponseHttpException(BaseErrorCode::$USER_IS_NOT_EXIST);
                }


                $request->userInfo = (object)$userInfo['data'];
                $action            = $request->route()->getAction('controller');
                $actionSplit       = explode('Controllers\\', $action);
                $controllerList    = strtolower(str_replace(['@', '\\', 'Controller'], ['.', '.', ''],
                    $actionSplit[1]));
                // 设置当前请求的uri
                $request->controllerUri = $controllerList;

                $request->setUserResolver(function () use ($userInfo) {
                    return (object)$userInfo["data"];
                });

                return $next($request);
            }
        }
        throw new UnauthorizedException();
    }

    /**
     * 将小程序的appid => platformName
     * @param Request $request
     * @return void
     */
    public static function convertAppIdToPlatformName(Request $request): string
    {
        $platformName = (string)$request->header('platformName');
        $appid        = $request->header('appid', '');

        if ($appid) {
            if (!$platformName) {
                $platformName = ConfigModel::getFsConfigByAppId($appid)['platformName'];

                $request->headers->set('platformName', $platformName);
            }
        }

        return $platformName;
    }

    /**
     * 选品建议飞书端登录获取用户信息
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function productSelectionProposalAuthorization(Request $request, Closure $next)
    {
        $userInfo = RmsUserService::getAuthUserInfo($request->headers->all());
        $id       = $userInfo['data']['id'] ?? 0;
        if ($id) {
            $action         = $request->route()->getAction('controller');
            $actionSplit    = explode('Controllers\\', $action);
            $controllerList = strtolower(str_replace(['@', '\\', 'Controller'], ['.', '.', ''], $actionSplit[1]));

            $request->controllerUri = $controllerList;

            $request->setUserResolver(
                function () use ($userInfo) {
                    return (object)$userInfo['data'];
                }
            );

            $request->userInfo = (object)$userInfo['data'];
            return $next($request);
        }
        throw new UnauthorizedException();
    }
}
